namespace ::

type Todo record { Content String, Done Bool(No) }

type OpPanel record {
    Widget Widget,
    Modify $[Null], Insert $[Null], MoveUp $[Null], MoveDown $[Null], Delete $[Null]
}
function OpPanel { is-first $[Bool], is-last $[Bool] } Hook[OpPanel] {
    @use modify = IconButton(Icon('accessories-text-editor'), 'Modify'),
    @use ins = IconButton(Icon('list-add'), 'Insert Below'),
    @use up = IconButton(Icon('go-up'), 'Move Up', (is-first map Not)),
    @use down = IconButton(Icon('go-down'), 'Move Down', (is-last map Not)),
    @use del = IconButton(Icon('list-remove'), 'Delete'),
    @use wrapper = Wrapper(Row(
        modify.Widget, ins.Widget, up.Widget, down.Widget, del.Widget
    )),
    Hook(new OpPanel(
        wrapper.Widget,
        modify.Clicks, ins.Clicks, up.Clicks, down.Clicks, del.Clicks
    ))
}

entry {
    ShowWindow({
        @use edit = ListEditView { select: N/A, initial: List[Todo](), content: { (todo,info) => {
            @use content = State(todo.Content),
            @use cb = CheckBox('', todo.Done),
            @use l = ElidedLabel(content.$),
            @use ops = OpPanel(info.IsFirst, info.IsLast),
            @use item = WrapperWithMargins(Row(cb.Widget, l.Widget, ops.Widget)),
            @use Style(item.Widget, {
                @map (index,_) = info.Pos,
                if (((index % 2) == 1)) { 'background-color: #EAEAEA;' }
                else { '' }
            }),
            @use Style(l.Widget, {
                @map done = cb.Checked,
                if (done) { 'text-decoration: line-through; color: gray; font-style: italic;' }
                else { 'font-weight: bold;' }
            }),
            @use Effect((content bind-override
                ops.Modify
                    | map-to-latest-from(content.$)
                    | exhaust-map({ current => GetLine('Modify Item:', current) })
            )),
            let insert = {
                ops.Insert
                    | exhaust-map({ => GetLine('New Item:') })
                    | map({ content => new Todo(content, No) })
            },
            ItemEditView {
                widgets:      item.Widget,
                update:       new:$ Todo(content.$, cb.Checked),
                delete:       ops.Delete,
                move-up:      ops.MoveUp,
                move-down:    ops.MoveDown,
                insert-below: insert
            }
        }}},
        @use Effect(DebugWatch('output', edit.Output)),
        @use add = PlainButton('Add'),
        @use buf = TextBox(''),
        @use Effect(edit | bind-update {
            prepend: {
                @map text = Merge(buf.TextOnEnters, buf.TextOn(add.Clicks)),
                new Todo(text)
            }
        }),
        Window($('Todo List'), Column(Row(buf.Widget,add.Widget),edit.Widget))
    })
}